package cn.sdormitory.controller.test;


import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.UUID;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.sdormitory.tencent.service.TencentCosFileService;
import io.jsonwebtoken.lang.Assert;
import net.coobird.thumbnailator.Thumbnails;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileItemFactory;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.tomcat.util.http.fileupload.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.commons.CommonsMultipartFile;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.*;

/**
 * 文件上传工具类
 */
@Component
public class FileUploadUtils {

    private static final int MAX_WIDTH = 454;
    private static final int MAX_HEIGHT = 440;

    @Autowired
    private TencentCosFileService cosFileService;

    public String uploadImageToTencentCos(MultipartFile file){
        return cosFileService.uploadImg(file);
    }

    public String uploadCompressorImageToTencentCos(MultipartFile file){
        file = compressImg(file);
        return cosFileService.uploadImg(file);
    }

    /**
     * 上传文件
     *
     * @param file
     * @return
     */
    public Result<String> upload(MultipartFile file, String dirPath) throws IOException {
        return upload(file,dirPath,false);
    }

    public Result<String> uploadCompressor(MultipartFile file, String dirPath) throws IOException {
        return upload(file, dirPath, true);
    }
    /**
     * 上传文件并压缩保存
     *
     * @param file
     * @return
     */
    public Result<String> upload(MultipartFile file, String dirPath, boolean compressor) throws IOException {
        Assert.notNull(file,"上传文件时文件不能为null");
        //上传目录地址
        String datePath = DateUtil.today();
        String uploadDir = FilePathUtils.getUploadDir(dirPath + File.separator +datePath);
        if (StrUtil.isBlank(uploadDir)) {
            return ResultUtil.error("获取上传目录失败");
        }
        if (ObjectUtil.isEmpty(file)) {
            return ResultUtil.error("文件不能为空");
        }
        if (StringUtils.isEmpty(file.getOriginalFilename())) {
            return ResultUtil.error("文件名不能为空");
        }
        if(compressor){
            file = compressImg(file);
        }
        //压缩图片
        String suffix;
        String fileName;
        FileOutputStream fileOutputStream = null;
        try {
            //调用上传方法
            //后缀名
            Assert.notNull(file.getOriginalFilename(),"上传文件时文件名称不能为null");
            suffix = file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf("."));
            fileName = UUID.fastUUID() + suffix;
            String fullFileName = uploadDir + "/" + fileName;
            fileOutputStream = new FileOutputStream(fullFileName);
            IOUtils.copy(file.getInputStream(), fileOutputStream);
            //String urlPathByFileName = FilePathUtils.getUrlPathByFileName(request, fileName);
            String relativeAddress = fullFileName.substring(fullFileName.indexOf(dirPath) + dirPath.length() + 1);
            return ResultUtil.data(relativeAddress);
        } catch (Exception e) {
            //打印错误堆栈信息
            e.printStackTrace();
            return ResultUtil.error(e.getMessage());
        } finally {
            if (fileOutputStream != null) {
                fileOutputStream.close();
            }
        }
    }

    /**
     * 压缩图片
     * @param multiFile
     * @return
     */
    public MultipartFile compressImg(MultipartFile multiFile) {
        // 压缩图片
        InputStream inputStream = null;
        ByteArrayOutputStream bos = null;
        MultipartFile multipartFile = null;
        InputStream fileInput= null;
        try {
            BufferedImage image = ImageIO.read(multiFile.getInputStream());
            int width = image.getWidth();
            int height = image.getHeight();

            // 计算目标宽度和高度
            int newWidth = width;
            int newHeight = height;
            if (width > MAX_WIDTH) {
                newWidth = MAX_WIDTH;
                newHeight = (int) ((double) height / width * newWidth);
            }
            if (newHeight > MAX_HEIGHT) {
                newHeight = MAX_HEIGHT;
                newWidth = (int) ((double) width / height * newHeight);
            }
            inputStream = multiFile.getInputStream();
            bos = new ByteArrayOutputStream();
            // 压缩图片核心代码
//            Thumbnails.of(inputStream).size(newWidth,newHeight).toOutputStream(bos);
            Thumbnails.of(inputStream).size(newWidth,newHeight).outputQuality(0.8f).outputFormat("jpg").toOutputStream(bos);
            fileInput = new ByteArrayInputStream(bos.toByteArray());
            // 转换 MultipartFile
            String fieldName = multiFile.getName();
            String fileName = multiFile.getOriginalFilename();
            String contentType = multiFile.getContentType();
            multipartFile = getMulFileByFile(fileInput, fieldName, contentType, fileName);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (inputStream != null){
                    inputStream.close();
                }
                if (bos != null){
                    bos.close();
                }
                if (fileInput != null){
                    fileInput.close();
                }
            } catch (IOException e) {
                e.printStackTrace();

            }
        }
        return multipartFile;
    }

    /**
     * 删除文件
     *
     * @param filePath
     * @return
     */
    public Result delete(String filePath) {
        File file = new File(filePath);
        if (Boolean.FALSE.equals(file.exists())) {
            return ResultUtil.error("文件不存在");
        }
        boolean delete = file.delete();
        if (Boolean.FALSE.equals(delete)) {
            return ResultUtil.error("删除失败");
        }
        return ResultUtil.success("");
    }

    private static MultipartFile getMulFileByFile(InputStream fis,String fieldName,String contentType,String fileName) {
        FileItem fileItem = createFileItem(fis,fieldName,contentType,fileName);
        return new CommonsMultipartFile(fileItem);
    }

    private static FileItem createFileItem(InputStream fis,String fieldName,String contentType,String fileName){
        FileItemFactory factory = new DiskFileItemFactory(16, null);
        FileItem item = factory.createItem(fieldName, contentType, false,fileName);
        int bytesRead = 0;
        byte[] buffer = new byte[8192];
        try
        {
            OutputStream os = item.getOutputStream();
            while ((bytesRead = fis.read(buffer, 0, 8192))!= -1)
            {
                os.write(buffer, 0, bytesRead);
            }
            os.close();
            fis.close();
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }
        return item;
    }

}
